package com.region.common.utils;

import com.region.common.adapter.logging.LoggerAdapter;
import com.region.common.adapter.logging.LoggerAdapterFactory;

import java.lang.reflect.Modifier;

/**
 * The Class utils
 *
 * @author liujieyu
 * @time 2023/5/23 23:26
 * @description
 */
public final class ClassUtils {

    private static final LoggerAdapter logger = LoggerAdapterFactory.getLogger(ClassUtils.class);

    /**
     * get default class loader
     *
     * @return
     */
    public static ClassLoader getClassLoader() {
        ClassLoader classLoader = null;
        try {
            classLoader = Thread.currentThread().getContextClassLoader();
        } catch (Throwable t) {
            //Cannot get thread context ClassLoader
        }
        if (classLoader == null) {
            // No thread context class loader -> use class loader of this class.
            classLoader = ClassUtils.class.getClassLoader();
            if (classLoader == null) {
                // getClassLoader() returning null indicates the bootstrap ClassLoader
                try {
                    classLoader = ClassLoader.getSystemClassLoader();
                } catch (Throwable ex) {
                    // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
                }
            }
        }
        return classLoader;
    }

    /**
     * Get all the classes of interface implemented by the object
     *
     * @param clazz the class of object
     * @return
     */
    public static Class<?>[] getAllInterfaces(Class<?> clazz) {
        Class<?>[] interfaces = clazz.getInterfaces();
        Class<?>[] superInterfaces = null;
        if (clazz.getSuperclass() != null) {
            superInterfaces = getAllInterfaces(clazz.getSuperclass());
        }
        if (superInterfaces == null && interfaces != null) {
            return interfaces;
        } else if (superInterfaces == null && interfaces == null) {
            return null;
        } else if (superInterfaces != null && interfaces == null) {
            return superInterfaces;
        } else {
            final int length = superInterfaces.length + interfaces.length;
            Class<?>[] result = new Class[length];
            System.arraycopy(interfaces, 0, result, 0, interfaces.length);
            System.arraycopy(superInterfaces, 0, result, interfaces.length, superInterfaces.length);
            return result;
        }
    }


    /**
     * create new instance by class object
     *
     * @param tClass
     * @param <T>
     * @return
     */
    public static <T> T newInstance(Class<T> tClass) {
        try {
            return tClass.newInstance();
        } catch (Throwable throwable) {
            logger.error("Cannot Load [" + tClass + "] Constructor, Error Message :" + throwable.getMessage());
            return null;
        }
    }

    /**
     * get CLass instance by class name and class have annotation
     *
     * @param className
     * @param annotation
     * @return
     */
    public static Class getInterfaceClass(String className, Class annotation) {
        try {
            Assert.notNull(className, "ClassName is Null");
            Class<?> clazz = Class.forName(className);
            if (annotation == null && Modifier.isInterface(clazz.getModifiers())) {
                return clazz;
            } else if (Modifier.isInterface(clazz.getModifiers()) && clazz.getDeclaredAnnotation(annotation) != null) {
                return clazz;
            }
            return null;
        } catch (Throwable e) {
            logger.error("The [" + className + "] is Not Loader ");
        }
        return null;
    }

    /**
     * get CLass instance by class object and class have annotation
     *
     * @param clazz
     * @param annotation
     * @return
     */
    public static Class getInterfaceClass(Class<?> clazz, Class annotation) {
        try {
            if (annotation == null && Modifier.isInterface(clazz.getModifiers())) {
                return clazz;
            } else if (Modifier.isInterface(clazz.getModifiers()) && clazz.getDeclaredAnnotation(annotation) != null) {
                return clazz;
            }
            return null;
        } catch (Throwable e) {
            logger.error("The [" + clazz + "] is Not Loader.");
        }
        return null;
    }
}
